package com.acdc.wechat.utils;

import java.nio.charset.StandardCharsets;

/**
 * 编码处理工具类
 * 用于处理微信API返回数据中的编码问题
 */
public class EncodingUtils {
    
    /**
     * 修复微信昵称的编码问题
     * 微信API返回的昵称可能存在编码问题，需要进行转换
     * 
     * @param nickname 原始昵称
     * @return 修复后的昵称
     */
    public static String fixWechatNickname(String nickname) {
        if (nickname == null || nickname.isEmpty()) {
            return nickname;
        }
        
        try {
            // 首先尝试直接修复常见的乱码模式
            String directFix = fixDirectGarbledText(nickname);
            if (directFix != null && !containsGarbledText(directFix)) {
                return directFix;
            }
            
            // 检查是否包含乱码字符
            if (containsGarbledText(nickname)) {
                // 尝试多种编码转换方式
                String result = tryMultipleEncodingConversions(nickname);
                if (result != null && !containsGarbledText(result)) {
                    return result;
                }
            }
            return nickname;
        } catch (Exception e) {
            // 如果转换失败，返回原始昵称
            return nickname;
        }
    }
    
    /**
     * 直接修复常见的乱码文本
     * 针对特定的乱码模式进行直接修复
     * 
     * @param text 原始文本
     * @return 修复后的文本
     */
    private static String fixDirectGarbledText(String text) {
        if (text == null) {
            return null;
        }
        
        try {
            // 方法1: 将文本按ISO-8859-1编码获取字节，然后用UTF-8重新解释
            byte[] bytes = text.getBytes(StandardCharsets.ISO_8859_1);
            String result = new String(bytes, StandardCharsets.UTF_8);
            
            // 检查结果是否包含中文字符且没有乱码
            if (result.matches(".*[\\u4e00-\\u9fa5].*") && !containsGarbledText(result)) {
                return result;
            }
            
            // 方法2: 尝试GBK编码
            String gbkResult = new String(bytes, "GBK");
            if (gbkResult.matches(".*[\\u4e00-\\u9fa5].*") && !containsGarbledText(gbkResult)) {
                return gbkResult;
            }
            
        } catch (Exception e) {
            // 忽略异常
        }
        
        return null;
    }
    
    /**
     * 尝试多种编码转换方式
     * 
     * @param text 原始文本
     * @return 转换后的文本
     */
    private static String tryMultipleEncodingConversions(String text) {
        // 方式1: 从UTF-8转换为ISO-8859-1，再转回UTF-8
        try {
            String result1 = new String(text.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
            result1 = new String(result1.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
            if (!containsGarbledText(result1)) {
                return result1;
            }
        } catch (Exception e) {
            // 忽略异常，继续尝试其他方式
        }
        
        // 方式2: 从ISO-8859-1转换为UTF-8
        try {
            String result2 = new String(text.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
            if (!containsGarbledText(result2)) {
                return result2;
            }
        } catch (Exception e) {
            // 忽略异常，继续尝试其他方式
        }
        
        // 方式3: 从GBK转换为UTF-8
        try {
            String result3 = new String(text.getBytes("GBK"), StandardCharsets.UTF_8);
            if (!containsGarbledText(result3)) {
                return result3;
            }
        } catch (Exception e) {
            // 忽略异常
        }
        
        // 方式4: 从UTF-8转换为GBK，再转回UTF-8
        try {
            String result4 = new String(text.getBytes(StandardCharsets.UTF_8), "GBK");
            result4 = new String(result4.getBytes("GBK"), StandardCharsets.UTF_8);
            if (!containsGarbledText(result4)) {
                return result4;
            }
        } catch (Exception e) {
            // 忽略异常
        }
        
        // 方式5: 针对特定乱码模式的处理（如 éåº -> 陈建）
        try {
            String result5 = fixSpecificGarbledPattern(text);
            if (result5 != null && !containsGarbledText(result5)) {
                return result5;
            }
        } catch (Exception e) {
            // 忽略异常
        }
        
        return null;
    }
    
    /**
     * 检查字符串是否包含乱码
     * 
     * @param text 要检查的文本
     * @return 是否包含乱码
     */
    private static boolean containsGarbledText(String text) {
        if (text == null) {
            return false;
        }
        
        // 检查是否包含常见的乱码字符模式
        // 1. 包含问号（通常表示无法识别的字符）
        if (text.contains("?")) {
            return true;
        }
        
        // 2. 检查是否包含连续的拉丁扩展字符（如 éåº）
        if (text.matches(".*[\\u00C0-\\u00FF]{2,}.*")) {
            return true;
        }
        
        // 3. 检查是否包含其他常见的乱码字符
        if (text.contains("") || text.contains("") || text.contains("")) {
            return true;
        }
        
        // 4. 检查是否包含控制字符
        if (text.matches(".*[\\p{Cntrl}&&[^\r\n\t]].*")) {
            return true;
        }
        
        return false;
    }
    
    /**
     * 安全地转换字符串编码
     * 
     * @param text 原始文本
     * @param fromCharset 源编码
     * @param toCharset 目标编码
     * @return 转换后的文本
     */
    public static String safeConvertEncoding(String text, String fromCharset, String toCharset) {
        if (text == null || text.isEmpty()) {
            return text;
        }
        
        try {
            return new String(text.getBytes(fromCharset), toCharset);
        } catch (Exception e) {
            // 转换失败时返回原始文本
            return text;
        }
    }
    
    /**
     * 针对特定乱码模式的处理
     * 处理类似 "éåº" -> "陈建" 的乱码情况
     * 
     * @param text 原始文本
     * @return 修复后的文本
     */
    private static String fixSpecificGarbledPattern(String text) {
        if (text == null) {
            return null;
        }
        
        try {
            // 将字符串转换为字节数组，然后尝试不同的编码解释
            byte[] bytes = text.getBytes(StandardCharsets.ISO_8859_1);
            
            // 尝试用UTF-8解释这些字节
            String utf8Result = new String(bytes, StandardCharsets.UTF_8);
            
            // 如果结果包含中文字符且不包含乱码，则返回
            if (utf8Result.matches(".*[\\u4e00-\\u9fa5].*") && !containsGarbledText(utf8Result)) {
                return utf8Result;
            }
            
            // 尝试用GBK解释这些字节
            String gbkResult = new String(bytes, "GBK");
            if (gbkResult.matches(".*[\\u4e00-\\u9fa5].*") && !containsGarbledText(gbkResult)) {
                return gbkResult;
            }
            
        } catch (Exception e) {
            // 忽略异常
        }
        
        return null;
    }
    
    /**
     * 清理和标准化文本
     * 移除或替换可能导致问题的特殊字符
     * 
     * @param text 原始文本
     * @return 清理后的文本
     */
    public static String cleanText(String text) {
        if (text == null) {
            return null;
        }
        
        // 移除控制字符，但保留换行符和制表符
        return text.replaceAll("[\\p{Cntrl}&&[^\r\n\t]]", "")
                  .trim();
    }
}
